#include <stdio.h>
#include "device.h"
#include <string.h>
#include <stdlib.h>
#include "esp_log.h"

#define TAG "DEVICE"

/* 全局注册表头指针 */
static struct device_registry *registry_heads[INIT_LEVEL_COUNT] = {NULL};

EXTERN_DEVICE_REGISTER(gpio_key);       //每一个注册的驱动在这里声明
// EXTERN_DEVICE_REGISTER(es8311);
EXTERN_DEVICE_REGISTER(pca9557);
EXTERN_DEVICE_REGISTER(st7789);

const device_register_t device_registry[] = {   //注册表
    DEVICE_REGISTER(gpio_key),
    // DEVICE_REGISTER(es8311),     //使用外部组件的dsp接口，不需要注册
    DEVICE_REGISTER(pca9557),        
    DEVICE_REGISTER(st7789),
};

/* 内部注册函数 */
void device_register(const struct device *dev, init_level_t level, uint8_t priority)
{
    struct device_registry *new_reg = malloc(sizeof(struct device_registry));
    new_reg->dev = (struct device *)dev;
    new_reg->init_level = level;
    new_reg->init_priority = priority;
    new_reg->initialized = false;
    new_reg->next = NULL;

    /* 按优先级插入链表 */
    struct device_registry **head = &registry_heads[level];
    
    /* 寻找插入位置 */
    while (*head && (*head)->init_priority < priority) {
        head = &(*head)->next;
    }
    
    /* 插入节点 */
    new_reg->next = *head;
    *head = new_reg;
}

/* 设备查找实现 */
struct device *device_get_binding(const char *name)
{
    /* 遍历所有级别 */
    for (int level = PRE_KERNEL_1; level < INIT_LEVEL_COUNT; ++level) {
        struct device_registry *current = registry_heads[level];
        
        while (current) {
            /* 比较设备名称 */
            if (strcmp(current->dev->config->name, name) == 0) {
                return current->dev;
            }
            current = current->next;
        }
    }
    return NULL;
}

/* 系统初始化实现 */
void device_init(void)
{
    for (int i = 0; i < sizeof(device_registry) / sizeof(device_register_t); ++i) {
        device_registry[i]();
    }

    /* 按级别顺序初始化 */
    for (int level = PRE_KERNEL_1; level < INIT_LEVEL_COUNT; ++level) {
        struct device_registry *current = registry_heads[level];
        
        while (current) {
            ESP_LOGI(TAG, "Init device %s at priority %d", current->dev->config->name, current->init_priority);
            /* 执行初始化函数 */
            if (current->dev->config->init) {
                current->dev->config->init((struct device *)current->dev);
            }
            current->initialized = true;
            
            /* 移动到下一个 */
            current = current->next;
        }
    }
}
